package com.m3958.firstgwt.server.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.QueryHint;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.eclipse.persistence.config.CacheUsage;
import org.eclipse.persistence.config.HintValues;
import org.eclipse.persistence.config.QueryHints;


import com.m3958.firstgwt.client.types.ObjectRoleName;
import com.m3958.firstgwt.server.types.HasObjectPermission;
import com.m3958.firstgwt.server.types.JsonExcludeFields;
import com.m3958.firstgwt.server.types.ObjectOperation;
import com.m3958.firstgwt.server.utils.JsonlibDateValueProssor;
import com.m3958.firstgwt.server.utils.ObjectPermissionUtil;


import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;

/**
 * 
 * @author Administrator
 * project这是通过消息添加，
 *
 */
@Entity
@Table(name="WF_PROJECT")
@AttributeOverride(name="id",column=@Column(nullable = false,name="WF_PROJECT_ID"))
@NamedQueries({
	@NamedQuery(name="findWorkProjectByUUID",
			query="SELECT w FROM WorkFlowProject AS w WHERE w.uuid = ?1",
			hints={@QueryHint(name=QueryHints.CACHE_USAGE, value=CacheUsage.DoNotCheckCache),
			@QueryHint(name=QueryHints.REFRESH, value=HintValues.TRUE)}),
	@NamedQuery(name="findWorkProjectByUserId",
			query="SELECT w FROM WorkFlowProject AS w WHERE w.creator.id = ?1 ORDER BY w.position ASC",
			hints={@QueryHint(name=QueryHints.CACHE_USAGE, value=CacheUsage.DoNotCheckCache),
					@QueryHint(name=QueryHints.REFRESH, value=HintValues.TRUE)}),
	@NamedQuery(name="findWorkProjectsByUUID",
			query="SELECT w FROM WorkFlowProject AS w WHERE w.path LIKE ?1 OR w.uuid = ?2 ORDER BY w.position ASC",
			hints={@QueryHint(name=QueryHints.CACHE_USAGE, value=CacheUsage.DoNotCheckCache),
					@QueryHint(name=QueryHints.REFRESH, value=HintValues.TRUE)})
					
})
public class WorkFlowProject extends BaseModel<WorkFlowProject> implements HasCreator,HasObjectPermission{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	public static class NamedQueries{
		public final static String FIND_PROJECT_BY_UUID = "findWorkProjectByUUID";
		public final static String FIND_PROJECTS_BY_UUID = "findWorkProjectsByUUID";
		public final static String FIND_BY_USER_ID = "findWorkProjectByUserId";
	}

	@Override
	public JSONObject toJson(){
		JsonConfig jc = new JsonConfig();
		jc.registerJsonValueProcessor(Date.class, injector.getInstance(JsonlibDateValueProssor.class));
		jc.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		jc.setExcludes(JsonExcludeFields.WF_EXCLUDES);
		return JSONObject.fromObject(this, jc);
	}
	
	private static ObjectOperation[] possibleOperations;
	
	private static ObjectRoleName[] possibleObjectRoles = ObjectRoleName.values();

	@Override
	public ObjectRoleName[] possibleRoleNames(){
		return possibleObjectRoles;
	}
	
	static{
		possibleOperations = ObjectOperation.values();
	}
	
	@Override
	public ObjectOperation[] possibleOperations(){
		return possibleOperations;
	}
	
	
	@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REMOVE})
	@JoinTable(name="WF_PROJECT_OBJECTPERMISSION")
	private List<Permission> objectPermissions = new ArrayList<Permission>();
	
	
	@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REMOVE})
	@JoinTable(name="WF_PROJECT_OBJECTROLE")
	private List<Role> objectRoles = new ArrayList<Role>();
	
	@Override
	public List<Permission> objectPermissions() {
		return objectPermissions;
	}

	public void setObjectPermissions(List<Permission> permissions) {
		this.objectPermissions = permissions;
	}
	
	
	public void createObjectPermissions(){
		ObjectPermissionUtil.createObjectPermissions(this);
	}
	
	
	
	public void createObjectRoles(){
		ObjectPermissionUtil.createObjectRoles(this);
	}
	
	public Role createObjectRole(ObjectRoleName orn){
		return ObjectPermissionUtil.createObjectRole(this, orn);
	}
	
	@Override
	public Role objectRole(ObjectRoleName orn){
		return ObjectPermissionUtil.getObjectRole(this, orn);
	}
	
	public void setObjectRoles(List<Role> roles) {
		this.objectRoles = roles;
	}

	@Override
	public List<Role> objectRoles() {
		return objectRoles;
	}
	
	public boolean addObjectRole(Role r){
		return ObjectPermissionUtil.addObjectRole(objectRoles, r);
	}
	
	public boolean addObjectPermission(Permission p){
		return ObjectPermissionUtil.addObjectPermission(objectPermissions, p);
	}

	@Override
	public String getOname() {
		return WorkFlowProject.class.getName();
	}
	
	@Override
	public Permission permission(ObjectOperation opCode) {
		return ObjectPermissionUtil.getPermission(this, opCode);
	}

	@Temporal(TemporalType.TIMESTAMP)
	private Date updatedAt;

	
	@Column(length=36)
	private String uuid;
	
	private int uid;
	
	@Lob
	private String title;
	
	@Lob
	private String note;
	
	private String shareType;//public,publicEditable,share,shareEditable,none
	
	@Lob
	private String path;
	
	@Column(length=36)
	private String dp;
	
	private boolean done;
	
	private boolean open;
	
	private long position;
	
	protected String creatorIds;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="CREATOR_ID",referencedColumnName="USER_ID")
	protected User creator;
	
	
	public User getCreator() {
		return creator;
	}

	public void setCreator(User creator) {
		this.creator = creator;
		if(creator != null)
			this.uid = creator.getId();
		creatorIds = getCreatorPath(creator);
	}

	public String getCreatorIds() {
		return creatorIds;
	}

	@Override
	public String[] getJsonExcludes() {
		return null;
	}

	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getNote() {
		return note;
	}

	public void setNote(String note) {
		this.note = note;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getDp() {
		return dp;
	}

	public void setDp(String dp) {
		this.dp = dp;
	}

	public boolean isDone() {
		return done;
	}

	public void setDone(boolean done) {
		this.done = done;
	}

	public boolean isOpen() {
		return open;
	}

	public void setOpen(boolean open) {
		this.open = open;
	}

	public void setUpdatedAt(Date updatedAt) {
		this.updatedAt = updatedAt;
	}

	public Date getUpdatedAt() {
		return updatedAt;
	}

	public void setPosition(long position) {
		this.position = position;
	}

	public long getPosition() {
		return position;
	}

	public void setShareType(String shareType) {
		this.shareType = shareType;
	}

	public String getShareType() {
		return shareType;
	}

	public int getUid() {
		if(uid == 0){
			if(getCreator() != null){
				return getCreator().getId();
			}
		}
		return uid;
	}
}
